<style lang="less">
/*左边工具栏以及编辑节点的样式*/
  @import "../../../assets/model-plugin/bpmn-js/dist/assets/diagram-js.css";
  @import "../../../assets/model-plugin/bpmn-js/dist/assets/bpmn-font/css/bpmn.css";
  @import "../../../assets/model-plugin/bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css";
  @import "../../../assets/model-plugin/bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css";
  /*右边工具栏样式*/
  @import "../../../assets/model-plugin/bpmn-js-properties-panel/dist/assets/bpmn-js-properties-panel.css";
  @import './decision-flow.less';
</style>

<template>
  <div>
    <div class="title-option-box">
      <h1 class="title">决策流</h1>
      <p class="option buttons">
        <Tooltip v-show="disabledTest" content="保存之后，才能进行测试" placement="left">
          <Button :disabled="disabledTest">测试</Button>
        </Tooltip>
        <Button v-show="!disabledTest" type="primary" @click="handleTestShow">测试</Button>
        <Button type="primary" @click="handleImport">导入</Button></Button>
        <Button type="primary" style="padding: 0">
          <a ref="saveDiagram" class="enable-link" href="javascript:;" title="download BPMN diagram">导出</a>
        </Button>
        <Button type="primary" @click="handleSave">保存</Button>
        <Button type="primary" @click="prevBtn">
          <Icon type="ios-arrow-back" size="15"></Icon>
        </Button>
        <Button @click="nextBtn" type="primary">
          <Icon type="ios-arrow-forward" size="15"></Icon>
        </Button>
      </p>
    </div>
    <div class="containers" ref="content">
      <div class="canvas" ref="canvas" style="margin-right: 20px"></div>
      <div id="js-properties-panel" class="panel"></div>
    </div>
    <test-modal ref="testModal"></test-modal>
    <upload-modal ref="uploadModal" @on-import-xml="importXMLAction"></upload-modal>
  </div>
</template>

<script>
// 引入相关的依赖
import BpmnModeler from '../../../assets/model-plugin/bpmn-js/lib/Modeler'
import propertiesPanelModule from '../../../assets/model-plugin/bpmn-js-properties-panel'
import propertiesProviderModule from '../../../assets/model-plugin/bpmn-js-properties-panel/lib/provider/camunda'
import camundaModdleDescriptor from '../../../assets/model-plugin/camunda-bpmn-moddle/resources/camunda.json'
// i18n语言转换
import customTranslate from '../../../assets/model-plugin/customTranslate/customTranslate'
// 规则转换逻辑
import { transferData } from '../../../libs/model-transform'
// 组件
import testModal from './test-modal'
import uploadModal from './upload-modal'

// api
import {
  getResInfo,
  getDecisionFlowContent,
  saveDecisionFlowContent
} from '../../../api/decision-flow'
import { showMessageTip } from '../../../libs/util'

export default {
  data () {
    return {
      bpmnModeler: null,
      container: null,
      canvas: null,
      xmlStr: null,
      disabledTest: true,
      processName: `processName_${Date.now().toString().substr(-4, 4)}`,
      resId: null, // 资源Id
      resProjectId: null, // 项目id
      resVerId: null // 版本id
    }
  },
  props: ['createId'],
  components: { testModal, uploadModal },
  methods: {
    getResIdAction (projectId) {
      this.resProjectId = projectId
      return new Promise((resolve, reject) => {
        getResInfo({
          projectId,
          resType: 'bpmn'
        }).then((result) => {
          const { code, data = {}, msg } = result.data || {}
          if (code === 2000) {
            const itemsObj = (data.items || [])[0]
            this.resId = itemsObj && itemsObj.resId
            resolve('success')
          } else {
            this.$Message.error(msg)
            // eslint-disable-next-line
            reject('fail')
          }
        })
      })
    },
    async initBpmn () {
      const { projectId } = this.$route.params
      // 获取当前资源的resId
      const resFlag = await this.getResIdAction(projectId)
      if (resFlag === 'success') {
        // 编辑
        const params = {
          resId: this.resId,
          projectId
        }
        // 获取资源的接口
        getDecisionFlowContent(params).then((result) => {
          const { code, msg } = result.data
          let { data } = result.data
          if (!data) {
            data = {}
          }
          if (code === 2000) {
            const initXmlStr = `<?xml version="1.0" encoding="UTF-8"?>
              <bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd" id="sample-diagram" targetNamespace="http://bpmn.io/schema/bpmn">
              <bpmn2:process id="defaultProcessId" name="${this.processName}" isExecutable="true">
              </bpmn2:process>
              <bpmndi:BPMNDiagram id="BPMNDiagram_1">
                <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="defaultProcessId">
                  <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
                    <dc:Bounds height="36.0" width="36.0" x="212.0" y="200.0"/>
                  </bpmndi:BPMNShape>
                </bpmndi:BPMNPlane>
              </bpmndi:BPMNDiagram>
            </bpmn2:definitions>`
            const { processContent = {}, resVerId = null } = data
            this.resVerId = resVerId
            const { camunda = initXmlStr } = processContent
            this.createNewDiagram(camunda)
          } else {
            this.$Message.error(msg)
          }
        })
      }
    },
    createNewDiagram (xmlStr) {
      const newDiagramXML =
        `<?xml version="1.0" encoding="UTF-8"?>
          <bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd" id="sample-diagram" targetNamespace="http://bpmn.io/schema/bpmn">
          <bpmn2:process id="defaultProcessId" name="${this.processName}" isExecutable="true">
            <bpmn2:startEvent id="StartEvent_1"/>
          </bpmn2:process>
          <bpmndi:BPMNDiagram id="BPMNDiagram_1">
            <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="defaultProcessId">
              <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
                <dc:Bounds height="36.0" width="36.0" x="212.0" y="200.0"/>
              </bpmndi:BPMNShape>
            </bpmndi:BPMNPlane>
          </bpmndi:BPMNDiagram>
        </bpmn2:definitions>`
      xmlStr = xmlStr || newDiagramXML
      this.importXMLAction(xmlStr)
    },
    importXMLAction (newDiagramXML) {
      // 导入xml字符串，显示视图
      this.bpmnModeler.importXML(newDiagramXML, (err) => {
        if (err) {
          this.$Message.error(err)
        } else {
          // 没有错误时，可以保存和下载
          const downloadLink = this.$refs.saveDiagram
          this.saveDiagram((err, xml) => {
            this.setEncoded(downloadLink, 'diagram.xml', err ? null : xml)
          })
        }
        // this.bpmnModeler.get('canvas').zoom('fit-viewport')
      })
    },
    saveDiagram (done) {
      // 把传入的done再传给bpmn原型的saveXML函数调用
      this.bpmnModeler.saveXML({ format: true }, (err, xml) => {
        done(err, xml)
      })
    },
    // 当图发生改变的时候会调用这个函数，这个data就是图的xml
    setEncoded (link, name, data) {
      // 把xml转换为URI，下载要用到的
      const encodedData = encodeURIComponent(data)
      // 获取到图的xml，保存就是把这个xml提交给后台
      this.xmlStr = data
      // console.log(5555, this.xmlStr);
      // 下载图的具体操作,改变a的属性，className令a标签可点击，href令能下载，download是下载的文件的名字
      if (data) {
        // xml存在时
        link.href = 'data:application/bpmn20-xml;charset=UTF-8,' + encodedData
        link.download = name
      }
    },
    saveDecisionFlowContentAction (finalStr) {
      const params = {
        contentType: 'bpmn',
        projectId: this.resProjectId,
        resId: this.resId,
        resVerId: this.resVerId,
        processContent: {
          camunda: this.xmlStr,
          jbpm: finalStr
        }
      }
      saveDecisionFlowContent(params).then((result) => {
        const { code, msg } = result.data
        const successMsg = '保存成功'
        showMessageTip(this, code, successMsg, msg)
        if (code === 2000) {
          this.disabledTest = false
          // 重新获取resVerId
          getDecisionFlowContent({
            projectId: this.resProjectId,
            resId: this.resId
          }).then(res => {
            const { code, data = {} } = res.data
            if (code === 2000) {
              const { resVerId = null } = data
              this.resVerId = resVerId
            }
          })
        }
      })
    },
    handleSave () {
      const { finalStr, bool } = transferData(this.xmlStr, this)
      if (bool) {
      // 校验通过
        this.saveDecisionFlowContentAction(finalStr)
      }
    },
    // 后退 前进
    prevBtn () {
      const params = {
        activeName: 'decisionFlow',
        option: 'prev'
      }
      this.$emit('on-move-forward', params)
    },
    nextBtn () {
      const params = {
        activeName: 'decisionFlow',
        option: 'next'
      }
      this.$emit('on-move-forward', params)
    },
    // 测试modal
    handleTestShow () {
      this.$refs.testModal.show({
        resId: this.resId,
        projectId: this.resProjectId
      })
    },
    //  导入modal
    handleImport () {
      this.$refs.uploadModal.show()
    }
  },
  mounted () {
    this.container = this.$refs.content
    const canvas = this.$refs.canvas
    const customTranslateModule = {
      translate: [ 'value', customTranslate ]
    }
    // 实例化
    this.bpmnModeler = new BpmnModeler({
      container: canvas,
      // 快捷键
      keyboard: {
        bindTo: window
      },
      // 添加控制板
      propertiesPanel: {
        parent: '#js-properties-panel'
      },
      additionalModules: [
        // 左侧的工具栏及节点
        propertiesPanelModule,
        // 右侧的工具栏
        propertiesProviderModule,
        customTranslateModule
      ],
      moddleExtensions: {
        camunda: camundaModdleDescriptor
      }
    })
    // 获取a标签dom节点
    const downloadLink = this.$refs.saveDiagram
    // 给图绑定事件，当图有发生改变就会触发这个事件* **（绑定事件操作）
    this.bpmnModeler.on('commandStack.changed', () => {
      this.disabledTest = true
      // 保存BPMN diagram格式的文件供后面下载
      this.saveDiagram((err, xml) => {
        this.setEncoded(downloadLink, 'diagram.xml', err ? null : xml)
      })
    })
    // 初始化时，只有保存之后才可以点击测试按钮
    // this.initBpmn()
    const { projectId } = this.$route.params
    if (projectId === '_create') {
      // 新增
      this.createNewDiagram()
    }
  },
  watch: {
    // 监听created属性在新增时执行
    createId (id) {
      this.resVerId = null // 生成新的项目时重置resVerId
      this.getResIdAction(id)
    }
  }
}
</script>
